
package com.wzc.common;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;

/**
 * @author wangzhichu
 * @description:
 * @date create in 2023/7/19 18:23
 * @modified
 */
@Aspect
@Slf4j
@Component
public class WebLogAspect {


    /** 以 controller 包下定义的所有请求为切入点 */
    @Pointcut(value = "execution(public * com.wzc.controller.*..*(..)))")
    public void webLog(){}

    /**
     * @apiNote 切点之前植入
     * @param joinPoint joinPoint
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        try {

            // 开始打印请求日志
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (Objects.isNull(attributes)){
                return;
            }
            assert attributes != null;
            HttpServletRequest request = attributes.getRequest();
            // 打印请求相关参数
           String sb = "".concat("请求 URL : ").concat(request.getRequestURL().toString())
                    .concat("\t请求 IP ：").concat( request.getRemoteAddr())
                    .concat("\t请求类名：").concat(joinPoint.getSignature().getDeclaringTypeName())
                    .concat("\t请求方法名 ：").concat(joinPoint.getSignature().getName())
                    .concat("\t请求 body ：").concat(JSONObject.toJSONString(joinPoint.getArgs()))
                    .concat("\t请求参数 ：").concat(JSONObject.toJSONString(request.getParameterMap()));
            log.info(String.format("Request Args   : %s", sb));
        } catch (Exception e) {
            log.info("Request Args catch error msg : {}");
        }
    }


    /**
     * 环绕
     * @param proceedingJoinPoint proceedingJoinPoint
     * @return Object
     * @throws Throwable Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        String meth = proceedingJoinPoint.getSignature().getName();
        // 打印出参 执行耗时
        log.info(String.format("接口 %s 执行时间: %s ms 返回结果: %s", meth, System.currentTimeMillis() - startTime, JSONObject.toJSONString(result)));
        // 结束
        return result;
    }

    @AfterThrowing( value = "webLog()", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, Exception ex) throws Throwable {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String requestURL = request.getRequestURL().toString();
        String meth = joinPoint.getSignature().getName();
        if (!StringUtils.isEmpty(requestURL)){
            meth = requestURL + " | " + meth;
        }

        Map<String, String[]> parameterMap = request.getParameterMap();
        String jsonString = null;
        if (CollectionUtils.isEmpty(parameterMap)){
            Object[] args = joinPoint.getArgs();
            jsonString = JSONObject.toJSONString(args);
        } else {
            jsonString = JSONObject.toJSONString(parameterMap);
        }
        log.info(String.format("接口异常 url:%s, 参数:%s, 异常:%s", meth, jsonString, ex.getMessage()));
    }
}
